<?php

namespace Library;

use Closure;
use Library\Traits\HasInstance;

/**
 * @method static Request make()
 */
class Request
{
    use HasInstance;
    private static ?Request $instance = null;



    public function __construct() {

    }

    private function handle(string $method, string|array $key = "", mixed $value = null){
        $method = strtoupper($method);
        $result = match ($method) {
            "GET" => $_GET,
            "POST" => $_POST,
            "REQUEST" => $_REQUEST,
            "SERVER" => $_SERVER,
            "COOKIE" => $_COOKIE,
            "SESSION" => $_SESSION??[],
            "ENV" => $_ENV,
            "FILES" => $_FILES,
            default => [],
        };
        if (!$key) return $result;
        if (is_array($key)){
            $num = 0;
            $values = array_map(function ($key) use ($result, $value, &$num) {
                $value = is_array($value)?($value[$num]??null):null;
                $res = $result[$key]??$value;
                $num++;
                return $res;
            },$key);
            return array_combine($key,$values);
        }
        return !empty($result[$key])?$result[$key]: $value;
    }

    /**
     * @param string|array $key
     * @param mixed $value
     * @return mixed
     */
    public function get(string|array $key = "", mixed $value = null): mixed
    {
        return $this->handle("GET",$key,$value);
    }

    /**
     * @param string|array $key
     * @param mixed $value
     * @return mixed
     */
    public function post(string|array $key = "", mixed $value = null): mixed
    {
        return $this->handle("POST",$key,$value);
    }

    /**
     * @param string|array $key
     * @param mixed $value
     * @return mixed
     */
    public function request(string|array $key = "", mixed $value = null): mixed
    {
        return $this->handle("REQUEST",$key,$value);
    }

    /**
     * @param string|array $key
     * @param mixed $value
     * @return mixed
     */
    public function server(string|array $key = "", mixed $value = null): mixed
    {
        return $this->handle("SERVER",$key,$value);
    }

    /**
     * @param string|array $key
     * @param mixed $value
     * @return mixed
     */
    public function cookie(string|array $key = "", mixed $value = null): mixed
    {
        return $this->handle("COOKIE",$key,$value);
    }

    /**
     * @param string|array $key
     * @param mixed $value
     * @return mixed
     */
    public function session(string|array $key = "", mixed $value = null): mixed
    {
        return $this->handle("SESSION",$key,$value);
    }

    /**
     * @param string|array $key
     * @param mixed $value
     * @return mixed
     */
    public function env(string|array $key = "", mixed $value = null): mixed
    {
        return $this->handle("ENV",$key,$value);
    }

    /**
     * @param string|array $key
     * @param mixed $value
     * @return mixed
     */
    public function files(string|array $key = "", mixed $value = null): mixed
    {
        return $this->handle("FILES",$key,$value);
    }

    /**
     * @param string $key
     * @return bool
     */
    public function isMethod(string $key): bool
    {
        $method = strtoupper($key);
        return $this->server("REQUEST_METHOD") === $method;
    }

    /**
     * @return bool
     */
    public function isGet(): bool
    {
        return $this->isMethod("GET");
    }

    /**
     * @return bool
     */
    public function isPost(): bool
    {
        return $this->isMethod("POST");
    }

    private function __clone() {}

}